import * as server from "@minecraft/server";
import * as derived_tools from "../system/derived_tools";
import * as native_tools from "../system/native_tools";
import * as math_tools from "../system/math_tools";
function CableQueue(object, type) {
    const getProtoArray = [];
    try {
        const portPositive_X = object.east();
        const portNegative_X = object.west();
        const portPositive_Y = object.above();
        const portNegative_Y = object.below();
        const portPositive_Z = object.south();
        const portNegative_Z = object.north();
        const getPoint = type.split(/\s+/)[0].split(/-/);
        switch (getPoint[0]) {
            case 'Xx':
                if (portPositive_X?.hasTag("data_tag:magic_cable.port_negative.X"))
                    getProtoArray.push(portPositive_X);
                if (portNegative_X?.hasTag("data_tag:magic_cable.port_positive.X"))
                    getProtoArray.push(portNegative_X);
                break;
            case 'X':
                if (portPositive_X?.hasTag("data_tag:magic_cable.port_negative.X"))
                    getProtoArray.push(portPositive_X);
                break;
            case 'x':
                if (portNegative_X?.hasTag("data_tag:magic_cable.port_positive.X"))
                    getProtoArray.push(portNegative_X);
                break;
            default: break;
        }
        ;
        switch (getPoint[1]) {
            case 'Yy':
                if (portPositive_Y?.hasTag("data_tag:magic_cable.port_negative.Y"))
                    getProtoArray.push(portPositive_Y);
                if (portNegative_Y?.hasTag("data_tag:magic_cable.port_positive.Y"))
                    getProtoArray.push(portNegative_Y);
                break;
            case 'Y':
                if (portPositive_Y?.hasTag("data_tag:magic_cable.port_negative.Y"))
                    getProtoArray.push(portPositive_Y);
                break;
            case 'y':
                if (portNegative_Y?.hasTag("data_tag:magic_cable.port_positive.Y"))
                    getProtoArray.push(portNegative_Y);
                break;
            default: break;
        }
        ;
        switch (getPoint[2]) {
            case 'Zz':
                if (portPositive_Z?.hasTag("data_tag:magic_cable.port_negative.Z"))
                    getProtoArray.push(portPositive_Z);
                if (portNegative_Z?.hasTag("data_tag:magic_cable.port_positive.Z"))
                    getProtoArray.push(portNegative_Z);
                break;
            case 'Z':
                if (portPositive_Z?.hasTag("data_tag:magic_cable.port_negative.Z"))
                    getProtoArray.push(portPositive_Z);
                break;
            case 'z':
                if (portNegative_Z?.hasTag("data_tag:magic_cable.port_positive.Z"))
                    getProtoArray.push(portNegative_Z);
                break;
            default: break;
        }
        ;
    }
    catch {
        derived_tools.ErrorMessage('<§l§b 魔导总线 §r>§4 发生错误§r', object, { text: '未能获取到<§l§d 魔导总线 §r>, 请勿在<§l§m 世界边界 §r>或<§l§n 世界之外 §r>使用' });
    }
    ;
    return getProtoArray.filter(info => {
        const state = info.permutation.getState('STATE:rune_type');
        return state === 0;
    });
}
;
function TryQueueState(queue, type, value) {
    try {
        queue.forEach(block => {
            const state = block.permutation.withState(type, value);
            block.setPermutation(state);
        });
    }
    catch (error) {
        return error;
    }
}
;
function Redstone(object, states) {
    try {
        const getRedstoneBlock = object.above()?.getRedstonePower();
        const getRedstoneSelf = states.getState('STATE:redstone');
        if (getRedstoneBlock != undefined) {
            if (getRedstoneBlock === getRedstoneSelf) {
                return true;
            }
            else {
                native_tools.TrySetPermutation(object, 'STATE:redstone', getRedstoneBlock);
                return false;
            }
        }
        else {
            native_tools.TrySetPermutation(object, 'STATE:redstone', 0);
            return true;
        }
    }
    catch {
        return false;
    }
}
;
export function RedstoneDetection(object, type) {
    if (!Redstone(object, object.permutation))
        TryQueueState(CableQueue(object, type), 'STATE:rune_type', math_tools.Random({ max: 7, min: 1 }, true));
}
;
function RunDetection(object, source) {
    for (let index = 1; index < 32; index++) {
        const getBlock = object.offset({ x: source.x * index, y: source.y * index, z: source.z * index });
        const state = getBlock?.permutation.getState('STATE:rune_type') ?? 9;
        if (!getBlock?.hasTag('data_tag:magic_cable.series') || state != 0)
            continue;
        native_tools.TrySetPermutation(getBlock, 'STATE:rune_type', object.permutation.getState('STATE:rune_type'));
        return getBlock;
    }
    ;
    return object;
}
;
export function SuperPulse(object, type) {
    try {
        server.system.run(() => native_tools.TrySetPermutation(object, 'STATE:rune_type', 9));
        switch (type) {
            case 'up': return RunDetection(object, math_tools.Vector.CONSTANT_UP);
            case 'down': return RunDetection(object, math_tools.Vector.CONSTANT_DOWN);
            case 'east': return RunDetection(object, math_tools.Vector.CONSTANT_EAST);
            case 'west': return RunDetection(object, math_tools.Vector.CONSTANT_WEST);
            case 'north': return RunDetection(object, math_tools.Vector.CONSTANT_NORTH);
            case 'south': return RunDetection(object, math_tools.Vector.CONSTANT_SOUTH);
            default: return object;
        }
        ;
    }
    catch {
        derived_tools.ErrorMessage('<§l§b 超导髓鞘 §r>§4 发生错误§r', object, { text: '无法发送<§l§c 总线信号 §r>, 请勿在<§l§m 世界边界 §r>或<§l§n 世界之外 §r>使用!!' });
        return object;
    }
    ;
}
;
export function SuperOmphalos(object, states) {
    try {
        ['up', 'down', 'north', 'south', 'west', 'east'].forEach(info => native_tools.TryFillBlocks(object.dimension, math_tools.Vector.add(object, { x: 11, y: 11, z: 11 }), math_tools.Vector.add(object, { x: -11, y: -11, z: -11 }), server.BlockPermutation.resolve('block_cable:super_pulse', {
            "STATE:rune_type": states.getState('STATE:rune_type'),
            "minecraft:block_face": info
        }), {
            blockFilter: {
                includePermutations: [
                    server.BlockPermutation.resolve('block_cable:super_pulse', {
                        "STATE:rune_type": 0,
                        "minecraft:block_face": info
                    })
                ]
            }
        }));
    }
    catch {
        derived_tools.ErrorMessage('<§l§b 超导枢纽 §r>§4 发生错误§r', object, { text: '无法发送<§l§c 总线信号 §r>, 请勿在<§l§m 世界边界 §r>或<§l§n 世界之外 §r>使用!!' });
    }
    ;
    native_tools.TrySetPermutation(object, 'STATE:rune_type', 9);
}
;
export function SignalCompilation(object, type, states) {
    const onError = () => {
        object.setPermutation(object.permutation.withState('STATE:stage', 2));
        object.setPermutation(object.permutation.withState('STATE:index', 0));
        derived_tools.ErrorMessage('<§l§b 信号编译 §r>§4 发生错误§r', object, { text: '未能在设备上方找到合适的<§l§3 方块容器 §r>' });
    };
    const aboveBlock = object.above();
    const getContainer = aboveBlock?.getComponent('minecraft:inventory')?.container;
    const getSlot = states.getState('STATE:index');
    if (!getContainer)
        return onError();
    if (getSlot >= getContainer.size || getSlot == 15) {
        native_tools.TrySetPermutation(object, 'STATE:stage', 2);
        native_tools.TrySetPermutation(object, 'STATE:index', 0);
        return;
    }
    ;
    const blocks = CableQueue(object, type);
    switch (getContainer.getItem(getSlot)?.typeId) {
        case 'item_crystal:blue_energy':
            TryQueueState(blocks, 'STATE:rune_type', 1);
            break;
        case 'item_crystal:red_energy':
            TryQueueState(blocks, 'STATE:rune_type', 2);
            break;
        case 'item_crystal:green_energy':
            TryQueueState(blocks, 'STATE:rune_type', 3);
            break;
        case 'item_crystal:orange_energy':
            TryQueueState(blocks, 'STATE:rune_type', 4);
            break;
        case 'item_crystal:purple_energy':
            TryQueueState(blocks, 'STATE:rune_type', 5);
            break;
        case '能量水晶:白星_魔晶石':
            TryQueueState(blocks, 'STATE:rune_type', 6);
            break;
        case '能量水晶:黑渊_魔晶石':
            TryQueueState(blocks, 'STATE:rune_type', 7);
            break;
        default:
            TryQueueState(blocks, 'STATE:rune_type', 0);
            break;
    }
    ;
    native_tools.TrySetPermutation(object, 'STATE:index', getSlot + 1);
}
;
export function interactiveTerminal(object, type, states) {
    const blocks = CableQueue(object, type);
    TryQueueState(blocks, 'STATE:rune_type', states.getState('STATE:rune_note'));
}
;
export function logicComponents(object, type) {
    const blocks = CableQueue(object, type);
    TryQueueState(blocks, 'STATE:rune_type', math_tools.Random({ max: 7, min: 1 }, true));
    if (object.typeId == 'block_cable:logic_inverter')
        return;
    for (let axleX = -1; axleX <= 1; axleX++)
        for (let axleY = -1; axleY <= 1; axleY++)
            for (let axleZ = -1; axleZ <= 1; axleZ++) {
                const block = object.offset({ x: axleX, y: axleY, z: axleZ });
                if (block?.typeId == 'block_cable:pulse_latch')
                    native_tools.TrySetPermutation(block, 'STATE:rune_note', 0);
            }
    ;
}
;
export function signalProcessing(object, type, states) {
    const blocks = CableQueue(object, type);
    TryQueueState(blocks, 'STATE:rune_type', states.getState('STATE:rune_note'));
    native_tools.TrySetPermutation(object, 'STATE:rune_type', 9);
}
;
function logicSingle(object) {
    const direction = object.permutation.getState('minecraft:block_face');
    function detection_up() {
        const input = object.offset(math_tools.Vector.CONSTANT_UP);
        const output = object.offset(math_tools.Vector.CONSTANT_DOWN);
        if (!input || !input?.hasTag('data_tag:magic_cable.open'))
            return;
        if (!output || !output?.hasTag('data_tag:magic_cable.series'))
            return;
        const states = input.permutation;
        native_tools.TrySetPermutation(output, 'STATE:rune_type', states.getState('STATE:rune_note'));
        server.system.runTimeout(() => native_tools.TrySetPermutation(input, 'STATE:rune_note', 0), 5);
    }
    ;
    function detection_down() {
        const input = object.offset(math_tools.Vector.CONSTANT_DOWN);
        const output = object.offset(math_tools.Vector.CONSTANT_UP);
        if (!input || !input?.hasTag('data_tag:magic_cable.open'))
            return;
        if (!output || !output?.hasTag('data_tag:magic_cable.series'))
            return;
        const states = input.permutation;
        native_tools.TrySetPermutation(output, 'STATE:rune_type', states.getState('STATE:rune_note'));
        server.system.runTimeout(() => native_tools.TrySetPermutation(input, 'STATE:rune_note', 0), 5);
    }
    ;
    function detection_north() {
        const input = object.offset(math_tools.Vector.CONSTANT_NORTH);
        const output = object.offset(math_tools.Vector.CONSTANT_SOUTH);
        if (!input || !input?.hasTag('data_tag:magic_cable.open'))
            return;
        if (!output || !output?.hasTag('data_tag:magic_cable.series'))
            return;
        const states = input.permutation;
        native_tools.TrySetPermutation(output, 'STATE:rune_type', states.getState('STATE:rune_note'));
        server.system.runTimeout(() => native_tools.TrySetPermutation(input, 'STATE:rune_note', 0), 5);
    }
    ;
    function detection_south() {
        const input = object.offset(math_tools.Vector.CONSTANT_SOUTH);
        const output = object.offset(math_tools.Vector.CONSTANT_NORTH);
        if (!input || !input?.hasTag('data_tag:magic_cable.open'))
            return;
        if (!output || !output?.hasTag('data_tag:magic_cable.series'))
            return;
        const states = input.permutation;
        native_tools.TrySetPermutation(output, 'STATE:rune_type', states.getState('STATE:rune_note'));
        server.system.runTimeout(() => native_tools.TrySetPermutation(input, 'STATE:rune_note', 0), 5);
    }
    ;
    function detection_west() {
        const input = object.offset(math_tools.Vector.CONSTANT_WEST);
        const output = object.offset(math_tools.Vector.CONSTANT_EAST);
        if (!input || !input?.hasTag('data_tag:magic_cable.open'))
            return;
        if (!output || !output?.hasTag('data_tag:magic_cable.series'))
            return;
        const states = input.permutation;
        native_tools.TrySetPermutation(output, 'STATE:rune_type', states.getState('STATE:rune_note'));
        server.system.runTimeout(() => native_tools.TrySetPermutation(input, 'STATE:rune_note', 0), 5);
    }
    ;
    function detection_east() {
        const input = object.offset(math_tools.Vector.CONSTANT_EAST);
        const output = object.offset(math_tools.Vector.CONSTANT_WEST);
        if (!input || !input?.hasTag('data_tag:magic_cable.open'))
            return;
        if (!output || !output?.hasTag('data_tag:magic_cable.series'))
            return;
        const states = input.permutation;
        native_tools.TrySetPermutation(output, 'STATE:rune_type', states.getState('STATE:rune_note'));
        server.system.runTimeout(() => native_tools.TrySetPermutation(input, 'STATE:rune_note', 0), 5);
    }
    ;
    switch (direction) {
        case 'up':
            detection_up();
            break;
        case 'down':
            detection_down();
            break;
        case 'north':
            detection_north();
            break;
        case 'south':
            detection_south();
            break;
        case 'west':
            detection_west();
            break;
        case 'east':
            detection_east();
            break;
        default: break;
    }
}
;
export function LatchUpdateEvent(object) {
    const blocks = [];
    for (let axleX = -1; axleX <= 1; axleX++)
        for (let axleY = -1; axleY <= 1; axleY++)
            for (let axleZ = -1; axleZ <= 1; axleZ++) {
                const Pointer = object.offset({ x: axleX, y: axleY, z: axleZ });
                if (Pointer)
                    blocks.push(Pointer);
            }
    ;
    blocks.forEach(block => {
        switch (block.typeId) {
            case 'block_cable:logic_single':
                logicSingle(block);
                break;
            case 'block_cable:logical_and':
                native_tools.TrySetPermutation(block, 'STATE:stage', 1);
                break;
            case 'block_cable:exclusive_or':
                native_tools.TrySetPermutation(block, 'STATE:stage', 1);
                break;
            default: break;
        }
    });
}
;
export function defaultEvent(object, type, state) {
    const blocks = CableQueue(object, type);
    TryQueueState(blocks, 'STATE:rune_type', state.getState('STATE:rune_type'));
    native_tools.TrySetPermutation(object, 'STATE:rune_type', 9);
}
;
